/**
 * http公共请求与回复头文件
 * 
 * 开发者   : Marco
 * 创建时间 : 2016年7月18日, 下午2:33
 */

#ifndef __MARCOPP_HTTP_BASIC_H__
#define __MARCOPP_HTTP_BASIC_H__

#include "../marcopp.h"
#include "../string.hpp"

#ifndef MARCOPP_NAMESPACE_HTTP
#define MARCOPP_NAMESPACE_HTTP_BEGIN namespace http {
#define MARCOPP_NAMESPACE_HTTP_END }
#endif

MARCOPP_NAMESPACE_BEGIN
MARCOPP_NAMESPACE_HTTP_BEGIN

/** 请求方法类别
 */
typedef enum {
    method_unknow = 0,
    method_get,
    method_post,
    method_put,
    method_delete,
} method_type;

/** http版本类别
 */
typedef enum {
    version_unknow = 0,
    version_1_0,	// HTTP/1.0
    version_1_1		// HTTP/1.1
} version_type;

/** 正文类型
 */
typedef enum {
    content_unknow = 0,
    content_json_utf8,
    content_texthtml_utf8,
} content_type;

/** 解析结果
 */
typedef enum {
    parse_success = 0,		// 成功
    parse_again,		// 未读完, 还要读正文
    parse_failed,		// 失败, 不是有效http报文
    parse_failed_method,	// 无法解析方法位置
    parse_failed_unknow_method,	// 方法不是指定的几种(GET, POST, PUT, DELETE)
    parse_failed_head,		// 解析协议头错误, 有非法的head行
    parse_failed_url,		// 无法解析URL位置
    parse_failed_params,	// 无法初始化URL参数
    parse_failed_version,	// 版本不是1.0也不是1.1
    parse_failed_length,	// 长度有问题, 读到的正文比报文中Content-Length还多
    parse_failed_status,	// 无法取到状态值
} parse_result;

class basic_impl;

class basic {
public:
    basic(version_type version = version_1_1);
    ~basic(void);
    
    /**
     * 版本号的获取与设置
     */
    version_type get_version(void) const;
    void set_version(version_type version);
    
    /**
     * 设置一条消息报头
     * @param name 名称
     * @param value 值
     */
    void set_msghead(string& name, string& value);
    void set_msghead(const char* name, const char* value);
    
    /**
     * 获取一条消息报头
     * @param name 名称
     * @return 值或NULL
     */
    const char* get_msghead(const char* name);
    
    void set_content_length(int content_length);    // 设置消息报头中Content-Length(正文长度)
    void set_real_content_length(void);		    // 根据正文内容实际长度, 设置协议头中的Content-Length头
    void set_cache_control(const char* cache_str);  // 设置消息报头中Cache-Control, 缓存控制
    void set_content_type(content_type ctype);	    // 设置消息报头中正文格式
    
    /**
     * 消息正文添加与获取
     * @param content_str
     */
    void append_content_str(string& content_str);
    void append_content_str(const char* content_str);
    void append_content_str(const char* content_str, int len);
    bool is_content_empty(void) const;	    // 正文是否为空
    string& get_content_str(void);	    // 获取正文内容
    const char* get_content_ptr(void) const;
    int get_content_length(void) const;	    // 获取正文长度
    
protected:
    /**
     * 从协议文本中初始化消息报头
     * @param data 协议内容首地址, 没有请求行与状态行, 解析会修改原数据.
     */
    bool init_msghead(char* data);
    
    /**
     * 获取消息报头字符串格式内容, 每行后增加\r\n, http整个头的\r\n不会添加
     * @param buf (out)存储区
     */
    void get_msghead_str(string& buf);
    int get_msghead_str(char* buf); // 由调用处保证足够大空间, 自动添加结束符0, 返回实际存储长度
    
private:
    basic_impl* impl;
};

MARCOPP_NAMESPACE_HTTP_END
MARCOPP_NAMESPACE_END
#endif /* __MARCOPP_HTTP_BASIC_H__ */